package com.zjc615.service.impl;

import com.zjc615.api.vo.NewBeeMallIndexCategoryVO;
import com.zjc615.api.vo.SecondLevelCategoryVO;
import com.zjc615.api.vo.ThirdLevelCategoryVO;
import com.zjc615.common.Constants;
import com.zjc615.common.NewBeeMallCategoryLevelEnum;
import com.zjc615.common.ServiceResultEnum;
import com.zjc615.dao.GoodsCategoryMapper;
import com.zjc615.entity.GoodsCategory;
import com.zjc615.service.NewBeeMallCategoryService;
import com.zjc615.util.BeanUtil;
import com.zjc615.util.PageQueryUtil;
import com.zjc615.util.PageResult;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;

import java.util.*;
import java.util.stream.Collectors;

import static java.util.stream.Collectors.groupingBy;

@Service
public class NewBeeMallCategoryServiceImpl implements NewBeeMallCategoryService {

    @Autowired
    private GoodsCategoryMapper goodsCategoryMapper;

    /**
     * 新增商品分类
     * 先通过分类等级和名称去看这个商品分类存不存在，如果存在就直接返回 “已存在同级同名的分类！”到前端，不存在就保存记录到数据库
     *
     * @param goodsCategory
     * @return
     */
    @Override
    public String saveCategory(GoodsCategory goodsCategory) {
        GoodsCategory temp = goodsCategoryMapper.selectByLevelAndName(goodsCategory.getCategoryLevel(), goodsCategory.getCategoryName());
        if (temp != null) {
            return ServiceResultEnum.SAME_CATEGORY_EXIST.getResult();
        }
        if (goodsCategoryMapper.insertSelective(goodsCategory) > 0) {
            return ServiceResultEnum.SUCCESS.getResult();
        }
        return ServiceResultEnum.DB_ERROR.getResult();
    }

    /**
     * 更新商品分类
     * 先通过商品分类的id去找到这个商品分类，如果找不到就返回“未查询到记录！”到前端，
     * 如果找到了，就再次以商品分类等级和商品分类名称去找商品分类的记录，
     * 如果修改了商品分类的名字，修改的商品名字已经存在则不能修改（防止重名）
     *
     * @param goodsCategory
     * @return
     */
    @Override
    public String updateGoodsCategory(GoodsCategory goodsCategory) {
        GoodsCategory temp = goodsCategoryMapper.selectByPrimaryKey(goodsCategory.getCategoryId());
        if (temp == null) {
            return ServiceResultEnum.DATA_NOT_EXIST.getResult();
        }
        GoodsCategory temp2 = goodsCategoryMapper.selectByLevelAndName(goodsCategory.getCategoryLevel(), goodsCategory.getCategoryName());
        if (temp2 != null && !temp2.getCategoryId().equals(goodsCategory.getCategoryId())) {
            //同名且不同id 不能继续修改
            return ServiceResultEnum.SAME_CATEGORY_EXIST.getResult();
        }
        goodsCategory.setUpdateTime(new Date());
        if (goodsCategoryMapper.updateByPrimaryKeySelective(goodsCategory) > 0) {
            return ServiceResultEnum.SUCCESS.getResult();
        }
        return ServiceResultEnum.DB_ERROR.getResult();
    }

    /**
     * 通过商品分类的id获取到商品分类
     *
     * @param id
     * @return
     */
    @Override
    public GoodsCategory getGoodsCategoryById(Long id) {
        return goodsCategoryMapper.selectByPrimaryKey(id);
    }

    /**
     * 通过id，删除一个或者多个商品分类
     *
     * @param ids
     * @return
     */
    @Override
    public Boolean deleteBatch(Long[] ids) {
        if (ids.length < 1) {
            return false;
        }
        //删除分类数据
        return goodsCategoryMapper.deleteBatch(ids) > 0;
    }

    /**
     * 获取首页的商品分类信息
     *
     * @return
     */
    @Override
    public List<NewBeeMallIndexCategoryVO> getCategoriesForIndex() {
        List<NewBeeMallIndexCategoryVO> newBeeMallIndexCategoryVOS = new ArrayList<>();
        //获取一级分类的固定数量的数据
        /**
         * List<GoodsCategory> selectByLevelAndParentIdsAndNumber(@Param("parentIds") List<Long> parentIds, @Param("categoryLevel") int categoryLevel, @Param("number") int number);
         * 其中的@Param是作用于mapper/GoodsCategoryMapper.xml的
         * Collections.singletonList(0L)                    创建一个只包含一个元素的 List 集合，该元素的值为 0L (长整型)
         * NewBeeMallCategoryLevelEnum.LEVEL_ONE.getLevel() 1
         * Constants.INDEX_CATEGORY_NUMBER                  10
         *
         * SQL:
         * SELECT
         * *
         * FROM tb_newbee_mall_goods_category
         * WHERE parent_id IN
         * (#{List<Long> parentIds})
         * AND category_level = #{int categoryLevel}
         * AND is_deleted = 0
         * ORDER BY category_rank DESC
         * LIMIT #{int number}
         * 其中 #{}对应形参的位置
         */
        List<GoodsCategory> firstLevelCategories = goodsCategoryMapper.selectByLevelAndParentIdsAndNumber(Collections.singletonList(0L), NewBeeMallCategoryLevelEnum.LEVEL_ONE.getLevel(), Constants.INDEX_CATEGORY_NUMBER);
        if (!CollectionUtils.isEmpty(firstLevelCategories)) {
            /**
             * 转化stream流 -> 将stream流中每个 GoodsCategory 对象转化为其 categoryId 属性的值 -> 收集stream流中所有元素到 firstLevelCategoryIds 集合中
             * 1.调用 firstLevelCategories.stream() 方法，将 firstLevelCategories 集合转化为一个 Stream 流；
             * 2.调用 map(GoodsCategory::getCategoryId) 方法，对 Stream 流中的每个元素 GoodsCategory 调用其 getCategoryId() 方法，将其转化为其 categoryId 属性的值；
             * 3.调用 collect(Collectors.toList()) 方法，将 Stream 流中的所有元素收集到一个新的 List 集合 firstLevelCategoryIds 中；
             * 4.返回 firstLevelCategoryIds 集合，该集合包含了 firstLevelCategories 集合中所有元素的 categoryId 属性的值。
             */
            List<Long> firstLevelCategoryIds = firstLevelCategories.stream().map(GoodsCategory::getCategoryId).collect(Collectors.toList());
            //获取二级分类的数据
            List<GoodsCategory> secondLevelCategories = goodsCategoryMapper.selectByLevelAndParentIdsAndNumber(firstLevelCategoryIds, NewBeeMallCategoryLevelEnum.LEVEL_TWO.getLevel(), 0);
            if (!CollectionUtils.isEmpty(secondLevelCategories)) {
                List<Long> secondLevelCategoryIds = secondLevelCategories.stream().map(GoodsCategory::getCategoryId).collect(Collectors.toList());
                //获取三级分类的数据
                List<GoodsCategory> thirdLevelCategories = goodsCategoryMapper.selectByLevelAndParentIdsAndNumber(secondLevelCategoryIds, NewBeeMallCategoryLevelEnum.LEVEL_THREE.getLevel(), 0);
                if (!CollectionUtils.isEmpty(thirdLevelCategories)) {
                    //根据 parentId 将 thirdLevelCategories 分组
                    /**
                     * 1.调用 thirdLevelCategories.stream() 方法，将 thirdLevelCategories 集合转化为一个 Stream 流；
                     * 2.调用 collect(groupingBy(GoodsCategory::getParentId)) 方法，对 Stream 流中的元素进行分组操作，使用 GoodsCategory::getParentId 作为分组依据；
                     * 3.分组操作会将具有相同 parentId 值的元素放入同一个列表中，并将结果存储在一个 Map 对象中；
                     * 4.返回 thirdLevelCategoryMap，该 Map 对象的键（Key）是 parentId 值（这个值是二级分类的id），值是具有相同 parentId 值的元素组成的列表。
                     */
                    Map<Long, List<GoodsCategory>> thirdLevelCategoryMap = thirdLevelCategories.stream().collect(groupingBy(GoodsCategory::getParentId));
                    //新建 自定义二级分类返回数据 列表
                    List<SecondLevelCategoryVO> secondLevelCategoryVOS = new ArrayList<>();
                    //处理二级分类，遍历二级分类数据
                    for (GoodsCategory secondLevelCategory : secondLevelCategories) {
                        SecondLevelCategoryVO secondLevelCategoryVO = new SecondLevelCategoryVO();
                        /**
                         * 对比 GoodsCategory 和 SecondLevelCategoryVO
                         * 发现 SecondLevelCategoryVO 只有 GoodsCategory的一部分属性值
                         * 所以 BeanUtil.copyProperties 就是把第一个参数的与部分属性值放到第二个参数里面的
                         */
                        BeanUtil.copyProperties(secondLevelCategory, secondLevelCategoryVO);
                        //如果该二级分类下有数据则放入 secondLevelCategoryVOS 对象中
                        if (thirdLevelCategoryMap.containsKey(secondLevelCategory.getCategoryId())) {
                            //根据二级分类的id取出thirdLevelCategoryMap分组中的三级分类list
                            List<GoodsCategory> tempGoodsCategories = thirdLevelCategoryMap.get(secondLevelCategory.getCategoryId());
                            //1.将属于二级分类id的三级分类数据（List<GoodsCategory>） 转化成 三级分类数据（List<ThirdLevelCategoryVO>）
                            //2.设置自定义二级分类返回数据 secondLevelCategoryVO 的 thirdLevelCategoryVOS 属性值为 三级分类数据（List<ThirdLevelCategoryVO>）
                            secondLevelCategoryVO.setThirdLevelCategoryVOS((BeanUtil.copyList(tempGoodsCategories, ThirdLevelCategoryVO.class)));
                            //自定义二级分类返回数据 列表 中新增 自定义二级分类返回数据
                            secondLevelCategoryVOS.add(secondLevelCategoryVO);
                        }
                    }
                    //到这里自定义二级分类返回数据 列表 就有数据了
                    //处理一级分类
                    if (!CollectionUtils.isEmpty(secondLevelCategoryVOS)) {
                        //根据 parentId 将 thirdLevelCategories 分组
                        /**
                         * 1.调用 secondLevelCategoryVOS.stream() 方法，将 secondLevelCategoryVOS 集合转化为一个 Stream 流；
                         * 2.调用 collect(groupingBy(GoodsCategory::getParentId)) 方法，对 Stream 流中的元素进行分组操作，使用 GoodsCategory::getParentId 作为分组依据；
                         * 3.分组操作会将具有相同 parentId 值的元素放入同一个列表中，并将结果存储在一个 Map 对象中；
                         * 4.返回 thirdLevelCategoryMap，该 Map 对象的键（Key）是 parentId 值（这个值是一级分类的id），值是具有相同 parentId 值的元素组成的列表。
                         */
                        Map<Long, List<SecondLevelCategoryVO>> secondLevelCategoryVOMap = secondLevelCategoryVOS.stream().collect(groupingBy(SecondLevelCategoryVO::getParentId));
                        for (GoodsCategory firstCategory : firstLevelCategories) {
                            NewBeeMallIndexCategoryVO newBeeMallIndexCategoryVO = new NewBeeMallIndexCategoryVO();
                            /**
                             * 对比 GoodsCategory 和 NewBeeMallIndexCategoryVO
                             * 发现 NewBeeMallIndexCategoryVO 只有 GoodsCategory的一部分属性值
                             * 所以 BeanUtil.copyProperties 就是把第一个参数的与部分属性值放到第二个参数里面的
                             */
                            BeanUtil.copyProperties(firstCategory, newBeeMallIndexCategoryVO);
                            //如果该一级分类下有数据则放入 newBeeMallIndexCategoryVOS 对象中
                            if (secondLevelCategoryVOMap.containsKey(firstCategory.getCategoryId())) {
                                //根据一级分类的id取出secondLevelCategoryVOMap分组中的二级级分类list
                                List<SecondLevelCategoryVO> tempGoodsCategories = secondLevelCategoryVOMap.get(firstCategory.getCategoryId());
                                newBeeMallIndexCategoryVO.setSecondLevelCategoryVOS(tempGoodsCategories);
                                newBeeMallIndexCategoryVOS.add(newBeeMallIndexCategoryVO);
                            }
                        }
                    }
                }
            }
            return newBeeMallIndexCategoryVOS;
        } else {
            return null;
        }
    }

    @Override
    public PageResult getCategoriesPage(PageQueryUtil pageUtil) {
        List<GoodsCategory> goodsCategories = goodsCategoryMapper.findGoodsCategoryList(pageUtil);
        int total = goodsCategoryMapper.getTotalGoodsCategories(pageUtil);
        PageResult pageResult = new PageResult(goodsCategories, total, pageUtil.getLimit(), pageUtil.getPage());
        return pageResult;
    }

    @Override
    public List<GoodsCategory> selectByLevelAndParentIdsAndNumber(List<Long> parentIds, int categoryLevel) {
        return goodsCategoryMapper.selectByLevelAndParentIdsAndNumber(parentIds, categoryLevel, 0);//0代表查询所有
    }
}
